#include "Steam2Fb.h"

#include <QDebug>
#include <QFile>
#include <QApplication>
#include <QNetworkRequest>
#include <QByteArray>

#include "data/Config.h"
#include "Wizard.h"

Steam2Fb::Steam2Fb(QObject *parent) :
    QSystemTrayIcon(parent)
{

    QApplication::setQuitOnLastWindowClosed(false);

    m_timer = new QTimer(this);
    connect(m_timer, SIGNAL(timeout()),
            this, SLOT(getSteamData()));

    config = Config::getInstance();

    m_nam = new QNetworkAccessManager(this);
    connect(m_nam, SIGNAL(finished(QNetworkReply*)),
            this, SLOT(gotReply(QNetworkReply*)));

    if (config->oAuthToken() == "")
    {
        Wizard *w = new Wizard(true);

        connect(w, SIGNAL(accepted()),
                this, SLOT(wizAccepted()));
        connect(w, SIGNAL(rejected()),
                this, SLOT(wizRejected()));

        w->show();
    }
    else
    {
        wizAccepted();
    }

}

void Steam2Fb::wizAccepted()
{
    config->save();
    m_hasSavedSteamData = loadSteamData();

    if (m_hasSavedSteamData)
    {
        QMapIterator<QString, Game> i(m_gameMap);
        while (i.hasNext())
        {
            i.next();
            qDebug() << "Loaded game: " << i.key();
        }
    }



    m_steamConnector = new SteamConnector(this);
    connect(m_steamConnector, SIGNAL(receivedSteamData(QMap<QString,Game>)),
            this, SLOT(steamData(QMap<QString,Game>)));

    m_timer->start(200);



}

void Steam2Fb::getSteamData()
{
    m_steamConnector->start();
    m_timer->start(600000);
}

void Steam2Fb::wizRejected()
{
    exit(0);
}

void Steam2Fb::steamData(QMap<QString, Game> gameMap)
{
    QList<Game> publishList;

    if (!m_hasSavedSteamData)
    {
        m_gameMap = gameMap;
        saveSteamData();
    }
    else
    {
        // see what is new

        bool needToSave = false;

        QMapIterator<QString, Game> i(gameMap);
        while (i.hasNext())
        {
            i.next();
            if (!m_gameMap.contains(i.key()))
            {
                qDebug() << "New game: " << i.key();
                m_gameMap.insert(i.key(), i.value());
                if (!i.value().achievements().empty())
                    publishList.append(i.value());
                needToSave = true;
            }
            else
            {
                // compare achievements
                Game g = i.value();
                Game updatedGame = i.value();
                QMap<QString, Achievement> currentAchievements =
                        m_gameMap.value(i.key()).achievements();

                g.clearAchievements();

                QMapIterator<QString, Achievement> ai(i.value().achievements());
                while (ai.hasNext())
                {
                    ai.next();

                    if ( ai.value().closed() &&
                        !currentAchievements.value(ai.key()).closed())
                    {
                        g.addAchievement(ai.value());
                        updatedGame.addAchievement(ai.value());
                        m_gameMap.insert(i.key(), updatedGame);
                        needToSave = true;

                        qDebug() << "*** New achievement *** : " << ai.key();
                    }
                    else if (!ai.value().closed() &&
                             !currentAchievements.contains(ai.key()))
                    {
                        // Handle case where a new achievement is added. This
                        // will be usefull if we want to display the achievements
                        updatedGame.addAchievement(ai.value());
                        m_gameMap.insert(i.key(), updatedGame);
                        needToSave = true;
                    }


                }

                if (!g.achievements().empty())
                    publishList.append(g);
            }
        }



        if (needToSave)
            saveSteamData();

        if (!publishList.empty())
            publishToFb(publishList);

    }
}

void Steam2Fb::publishToFb(QList<Game> pubList)
{


    while(!pubList.empty())
    {
        Game game = pubList.takeFirst();



        QMap<QString, Achievement> aMap = game.achievements();

        QString attachment = "message=has unlocked " +
                             QString::number(aMap.count()) +
                             " new Steam Achievement";
        if (aMap.count() > 1)
            attachment.append("s");

        attachment.append(" in " + game.name() +
                          "!&attachment={\"description\" : \"");


        QMapIterator<QString, Achievement> i(aMap);

        QList<QString> imgList;

        while (i.hasNext())
        {
            i.next();
            attachment.append(i.value().name() +
                              " (" + i.value().description() +
                              ")");
            attachment.append(", ");
            imgList.append(i.value().iconUrl());
        }

        attachment.chop(2);

        attachment.append("\", \"media\" : [");

        QString href = game.statsUrl();
        href = href.remove("&xml=1");

        while (!imgList.empty())
        {
            attachment.append("{ \"type\" : \"image\", \"src\" : \"" +
                              imgList.takeFirst() +
                              "\",\"href\" : \"" + href + "\"},");
        }

        attachment.chop(1);
        attachment.append("]}");



        qDebug() << attachment;

        QByteArray postArgs;
        postArgs.append(attachment);

        QByteArray exclude("&=");
        QByteArray include;
        postArgs = postArgs.toPercentEncoding(exclude,include,'%');

        qDebug() << postArgs;

        postArgs.append("&token=");
        postArgs.append(config->oAuthToken());

        QUrl url("https://api.facebook.com/method/stream.publish");
        QNetworkRequest nr;
        nr.setUrl(url);
        nr.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
        m_nam->post(nr,postArgs);


    }


}


void Steam2Fb::gotReply(QNetworkReply *reply)
{
    if (reply->error() == QNetworkReply::NoError)
    {
        qDebug() << reply->readAll();


    }
    else
    {
        qDebug() << reply->errorString();
    }
}

bool Steam2Fb::loadSteamData()
{
    qDebug() << "Loading steam data";

    QFile file(config->saveDir() + "/steam2fb.dat");
    if (!file.open(QIODevice::ReadOnly))
    {
        return false;
    }

    QDataStream in(&file);
    in.setVersion(QDataStream::Qt_4_6);
    in >> m_gameMap;
    return true;
}

bool Steam2Fb::saveSteamData()
{
    qDebug() << "Saving steam data";
    QFile file(config->saveDir() + "/steam2fb.dat");
    if (!file.open(QIODevice::WriteOnly))
    {
        return false;
    }

    QDataStream out(&file);
    out.setVersion(QDataStream::Qt_4_6);
    out << m_gameMap;

    m_hasSavedSteamData = true;
    return true;
}

